#ifndef __DYNAMIC_LIBRARY_H__
#define __DYNAMIC_LIBRARY_H__

////////////////////////////////////////////////////////////////////////////////
// Includes
////////////////////////////////////////////////////////////////////////////////

#include <string>

// Include system 
#ifdef __UNIX__
	#include <dlfcn.h>
#else
#ifdef __MSW__
	#include <windows.h>
#else
	#error "Not implemented for the current OS"
#endif
#endif

////////////////////////////////////////////////////////////////////////////////
// Namespaces
////////////////////////////////////////////////////////////////////////////////

namespace Toolkit {

////////////////////////////////////////////////////////////////////////////////
// Implementation
////////////////////////////////////////////////////////////////////////////////

/// Generic function pointer
typedef void * FuncPtr;

/**
 *  This class defines a dynamic library manager
 */
class DynamicLibrary {

	public:
		
		/// Constructor
		DynamicLibrary();
		
		/// Create a copy of the given instance
		DynamicLibrary(const DynamicLibrary &);
		
		/// Destructor
		virtual ~DynamicLibrary();
		
		/// Affectation operator
		DynamicLibrary & operator = (const DynamicLibrary &);
		
		/// Attaches the plugin given by its file name
		void Attach(const std::string &);
		
		/// Returns true if the plugin is loaded
		const bool IsLoaded();

		/// Detaches the plugin
		void Detach();
		
		/// Get a method pointer from its name
		FuncPtr GetFunction(const std::string &);
		
		/// Returns library file name
		const std::string & GetFileName() const { return this->file_name; }
		
	protected:

		/// Library file name
		std::string file_name;
		
		/// Library handle
#ifdef __UNIX__
		void * handle;
#else
#ifdef __MSW__
		HINSTANCE handle;
#endif
#endif

		/// Returns the last error message
		const std::string getLastError();

};

////////////////////////////////////////////////////////////////////////////////
// Closing Namespaces
////////////////////////////////////////////////////////////////////////////////

}

////////////////////////////////////////////////////////////////////////////////

#endif
